/**
 * Created by Administrator on 2017/8/28.
 */
let msg = require('../util/msg.js');
let util = require('../util/util.js');
let log = require('../util/log.js');
let DDZ = require('./ddz/ddz.js');
let DDZHandler = require('./ddz/handler.js');
let Player = require('./ddz/player.js');
let variable = require('../data/variable.js');
let gameData = require('../util/gameData.js');
let mem = require('../util/mem.js');
let rpc = require('../util/rpc.js');
let save = require('./save.js');

let method = module.exports;

method.join = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    if (mem.gamePlayers[obj.userId].timeoutJoin) {
        clearTimeout(mem.gamePlayers[obj.userId].timeoutJoin);
        delete mem.gamePlayers[obj.userId].timeoutJoin;
    }
    if (mem.gamePlayers[obj.userId].line == 'on') {
        msg.send(cid, obj.uuid, 'error', {'code': 10033});
        return false;
    }
    if (cid) {
        mem.gamePlayers[obj.userId].line = 'on';
    } else {
        mem.gamePlayers[obj.userId].line = 'off';
    }
    mem.gamePlayers[obj.userId].inRoom = true;
    mem.gamePlayers[obj.userId].cid = cid;
    mem.gamePlayers[obj.userId].uuid = obj.uuid;
    if (game.ddz) {
        game.ddz.getPlayer(mem.gamePlayers[obj.userId].local).setCid(cid);
        game.ddz.getPlayer(mem.gamePlayers[obj.userId].local).setUuid(obj.uuid);
        game.ddz.getPlayer(mem.gamePlayers[obj.userId].local).setStay(true);
    }
    let playerInfo = {};
    let playerNum = 0;
    let coinType = gameData.d.gameLv[game.lv].coinType;
    for (let i in game.id) {
        let id = game.id[i];
        if (!mem.gamePlayers[id].inRoom) {
            continue;
        }
        playerInfo[mem.gamePlayers[id].local] = {
            'id': mem.gamePlayers[id].id,
            'name': mem.gamePlayers[id].name,
            'avatar': mem.gamePlayers[id].avatar,
            'coin': mem.gamePlayers[id].coin,
            'ready': mem.gamePlayers[id].ready
        };
        playerNum++;
    }
    msg.send(cid, obj.uuid, 'gameJoin', {
        'local': mem.gamePlayers[obj.userId].local,
        'gameType': gameData.d.gameLv[game.lv].type,
        'coinType': gameData.d.gameLv[game.lv].coinType
    });
    if (!game.ddz) {
        broadcast(game.id, 'gamePlayer', playerInfo);
    } else {
        msg.send(cid, obj.uuid, 'gamePlayer', playerInfo);
    }
    if (game.ddz) {
        let gameReconnect = {};
        gameReconnect.local = mem.gamePlayers[obj.userId].local;
        gameReconnect.state = game.ddz.getStateName();
        gameReconnect.baseScore = game.ddz.getBaseScore();
        gameReconnect.multiple = game.ddz.getMultiple();
        gameReconnect.multiples = game.ddz.getMultiples();
        gameReconnect.ticket = game.ddz.getTicket();
        gameReconnect.winCap = game.ddz.getWinCap();
        gameReconnect.previous = game.ddz.getPreviousID();
        gameReconnect.next = game.ddz.getNext() % 3;
        gameReconnect.lord = game.ddz.getDZ();
        gameReconnect.restTime = game.ddz.getTimeoutTime();
        gameReconnect.restTimeStamp = game.ddz.getTimeoutTimeStamp();
        if (game.ddz.statusIsPlaying()) {
            gameReconnect.desktopCards = game.ddz.getHoleCards();
        } else {
            gameReconnect.desktopCards = null;
        }
        gameReconnect.myCards = game.ddz.getPlayer(mem.gamePlayers[obj.userId].local).getHandCards();
        gameReconnect.lastHands = {};
        gameReconnect.cardNum = {};
        gameReconnect.askScore = {};
        gameReconnect.isAuto = {};
        gameReconnect.double = {};
        for (let j = 0; j < 3; j++) {
            gameReconnect.lastHands[j] = game.ddz.getPlayer(j).getLastHands();
            gameReconnect.cardNum[j] = game.ddz.getPlayer(j).getHandCards().length;
            gameReconnect.askScore[j] = game.ddz.getPlayer(j).getScore();
            gameReconnect.isAuto[j] = game.ddz.getPlayer(j).isAutoPlay();
            gameReconnect.double[j] = game.ddz.getPlayer(j).isDouble();
        }
        game.ddz.sendTo(mem.gamePlayers[obj.userId].local, 'gameReconnect', gameReconnect);
        if (game.ddz.statusIsPlaying()) {
            //game.ddz.addManaged(mem.gamePlayers[uid].local, false);
        }
    } else if (playerNum >= 3) {
        for (let i in game.id) {
            let id = game.id[i];
            if (!mem.gamePlayers[id].ready && mem.gamePlayers[id].inRoom) {
                //if (!mem.gamePlayers[id].ready && mem.gamePlayers[id].line == 'on') {
                msg.send(mem.gamePlayers[id].cid, mem.gamePlayers[id].uuid, 'gameNeedReady');
                if (gameData.d.gameLv[game.lv].type != 'custom') {
                    mem.gamePlayers[id].timeoutReady = setTimeout(function () {
                        method.ready(obj, cid, data);
                    }, (gameData.d.config.readyTimeout * 1000));
                }
            }
        }
    }
};
method.ready = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    if (mem.gamePlayers[obj.userId].timeoutReady) {
        clearTimeout(mem.gamePlayers[obj.userId].timeoutReady);
        delete mem.gamePlayers[obj.userId].timeoutReady;
    }
    if (game.ddz) {
        msg.send(cid, obj.uuid, 'error', {'code': 10040});
        return false;
    }
    let allInRoom = true;
    if (Object.keys(game.id).length < 3) {
        allInRoom = false;
    } else {
        for (let i in game.id) {
            let id = game.id[i];
            if (!mem.gamePlayers[id].inRoom) {
                allInRoom = false;
            }
        }
    }
    if (!allInRoom) {
        msg.send(cid, obj.uuid, 'error', {'code': 10034});
        return false;
    }
    mem.gamePlayers[obj.userId].ready = !mem.gamePlayers[obj.userId].ready;
    let playerReady = {};
    let ready = true;
    for (let i in game.id) {
        let id = game.id[i];
        playerReady[mem.gamePlayers[id].local] = mem.gamePlayers[id].ready;
        if (!mem.gamePlayers[id].ready) {
            ready = false;
        }
    }
    broadcast(game.id, 'gameReady', playerReady);

    // 如果还没都准备好
    if (ready == false || Object.keys(game.id).length < 3) {
        return false;
    }

    // 实例化桌台
    if (!game.ddz) {
        let p = {};
        for (let i in game.id) {
            let id = game.id[i];
            p[mem.gamePlayers[id].local] = new Player(id, mem.gamePlayers[id].name,
                mem.gamePlayers[id].cid, mem.gamePlayers[id].uuid);
            p[mem.gamePlayers[id].local].setCoin(mem.gamePlayers[id].coin);
            if (mem.gamePlayers[id].robot) {
                p[mem.gamePlayers[id].local].setAiLevel(2);
                p[mem.gamePlayers[id].local].setRobot(true);
                p[mem.gamePlayers[id].local].setAutoPlay(true);
                //game.ddz.addManaged(mem.gamePlayers[id].local, true);
            }
        }
        if (!p[0] || !p[1] || !p[2]) {
            return false;
        }
        game.ddz = new DDZ(game.gameId);
        game.ddz.setGameLv(game.lv);
        game.ddz.setEventHandle(new DDZHandler());
        game.ddz.start(p[0], p[1], p[2], function () {
            try {
                game.ddz.sendTo(0, 'gameStart', {
                    //'desktopCards': game.ddz.getHoleCards(),
                    'myCards': game.ddz.getPlayer(0).getHandCards()
                });
                game.ddz.sendTo(1, 'gameStart', {
                    //'desktopCards': game.ddz.getHoleCards(),
                    'myCards': game.ddz.getPlayer(1).getHandCards()
                });
                game.ddz.sendTo(2, 'gameStart', {
                    //'desktopCards': game.ddz.getHoleCards(),
                    'myCards': game.ddz.getPlayer(2).getHandCards()
                });
                game.ddz.setBaseScore(gameData.d.gameLv[game.lv].baseChip);
                game.ddz.setTicket(gameData.d.gameLv[game.lv].ticket);
                game.ddz.setWinCap(gameData.d.gameLv[game.lv].winCap);
                if (gameData.d.gameLv[game.lv].type == 'custom') {
                    let param = {};
                    param.gameId = game.gameId;
                    rpc.dc.send('delRecruit', param);
                }
            } catch (e) {
                log.e(game, p[0], p[1], p[2]);
            }
        });
    }
};
method.askChip = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    if (!game.ddz) {
        msg.send(cid, obj.uuid, 'error', {'code': 10035});
        return false;
    }
    //if (gameData.d.gameLv[game.ddz.getGameLv()].type == 'happy'){
    //    if (!game.ddz.askDZ(mem.gamePlayers[obj.userId].local, data.chip)) {
    //        game.ddz.sendTo(mem.gamePlayers[obj.userId].local, 'error', {'code': 10039});
    //        return false;
    //    }
    //}else {
    if (!game.ddz.askScore(mem.gamePlayers[obj.userId].local, data.chip)) {
        game.ddz.sendTo(mem.gamePlayers[obj.userId].local, 'error', {'code': 10039});
        return false;
    }
    //}
    //game.ddz.sendAskChip();
};
method.askDz = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    if (!game.ddz) {
        msg.send(cid, obj.uuid, 'error', {'code': 10035});
        return false;
    }
    if (!game.ddz.askDZ(mem.gamePlayers[obj.userId].local, data.chip)) {
        game.ddz.sendTo(mem.gamePlayers[obj.userId].local, 'error', {'code': 10039});
        return false;
    }
    //game.ddz.sendAskDZ();
};
method.robDZ = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    if (!game.ddz) {
        msg.send(cid, obj.uuid, 'error', {'code': 10035});
        return false;
    }
    if (!game.ddz.robDZ(mem.gamePlayers[obj.userId].local, data.chip)) {
        game.ddz.sendTo(mem.gamePlayers[obj.userId].local, 'error', {'code': 10038});
        return false;
    }
    //game.ddz.sendAskDZ();
};
method.double = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    if (!game.ddz) {
        msg.send(cid, obj.uuid, 'error', {'code': 10035});
        return false;
    }
    if (!game.ddz.double(mem.gamePlayers[obj.userId].local, data.double)) {
        game.ddz.sendTo(mem.gamePlayers[obj.userId].local, 'error', {'code': 10049});
        return false;
    }
};
method.play = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    if (!game.ddz) {
        msg.send(cid, obj.uuid, 'error', {'code': 10035});
        return false;
    }
    let play = game.ddz.play(mem.gamePlayers[obj.userId].local, data.idList);
    if (typeof (play) == 'number') {
        let code = 0;
        switch (play) {
            case 1://当前不由你出牌
                code = 10041;
                break;
            case 2://不能再PASS了
                code = 10042;
                break;
            case 3://牌型错误
                code = 10043;
                break;
            case 4://牌型不一致
                code = 10044;
                break;
            case 5://不大于上家
                code = 10045;
                break;
            default://迷之错误
                code = 10046;
                break;
        }
        game.ddz.sendTo(mem.gamePlayers[obj.userId].local, 'error', {'code': code});
    }
};
method.showCard = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    if (!game.ddz) {
        msg.send(cid, obj.uuid, 'error', {'code': 10035});
        return false;
    }
    game.ddz.showCard(mem.gamePlayers[obj.userId].local);
};
method.auto = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    if (!game.ddz) {
        msg.send(cid, obj.uuid, 'error', {'code': 10035});
        return false;
    }
    //if (!game.ddz.statusIsPlaying()) {
    //    msg.send(cid, obj.uuid, 'error', {'code': 10048});
    //    return false;
    //}
    // 修改 1 > 2
    game.ddz.getPlayer(mem.gamePlayers[obj.userId].local).setAiLevel(2);
    game.ddz.addManaged(mem.gamePlayers[obj.userId].local);
};
method.msg = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    if (!data.msgId) {
        msg.send(cid, obj.uuid, 'error', {'code': 10047});
        return false;
    }
    broadcast(game.id, 'gameMsg', {
        'msgId': data.msgId,
        'local': mem.gamePlayers[obj.userId].local,
        'target': data.target
    });
};
method.exit = function (obj, cid, data) {
    let game = getGame(obj, cid);
    if (!game) {
        return false;
    }
    mem.gamePlayers[obj.userId].line = 'off';
    //mem.gamePlayers[uid].uuid = null;
    //mem.gamePlayers[uid].cid = null;
    if (game.ddz) {
        if (game.ddz.getPlayer(mem.gamePlayers[obj.userId].local) != null) {
            game.ddz.getPlayer(mem.gamePlayers[obj.userId].local).setStay(false);
        }
        //game.ddz.addManaged(mem.gamePlayers[uid].local, true);
    } else {
        let exit = gameData.d.gameLv[game.lv].exit;
        if (exit) {
            delete mem.gamePlayers[obj.userId];
            save.clearGameId(obj.userId, cid, obj.uuid);
            let idx = game.id.indexOf(obj.userId);
            game.id.splice(idx, 1);
        }
    }

    let allEscape = true;
    let gameExit = {};
    for (let i = 0; i < 3; i++) {
        gameExit[i] = {};
        //gameExit[i].ai = 'off';
        gameExit[i].leave = true;
    }
    for (let i in game.id) {
        let id = game.id[i];
        if (!mem.gamePlayers[id]) {
            continue;
        }
        gameExit[mem.gamePlayers[id].local].leave = false;
        //gameExit[mem.gamePlayers[id].local].ai = mem.gamePlayers[id].line;
        if (mem.gamePlayers[id].line != 'off') {
            allEscape = false;
        }
    }
    broadcast(game.id, 'gameExit', gameExit);
    msg.send(cid, obj.uuid, 'gameExited', {'gameId': game.gameId});

    // 判断是否全部人都逃跑从而删除房间
    if (allEscape) {
        let gameId = game.gameId;
        let gameLv = game.lv;
        let coinType = gameData.d.gameLv[game.lv].coinType;
        let escapeCoin = 0;
        if (game.ddz && game.ddz.getBaseScore() > 0 && game.ddz.getMultiple() > 0) {
            escapeCoin += game.ddz.getBaseScore() * game.ddz.getMultiple() * gameData.d.config.killGamePunish;
        }
        if (game.ddz && game.ddz.getTicket() > 0) {
            escapeCoin += game.ddz.getTicket();
        }
        for (let j = 0; j < 3; j++) {
            if (!mem.gamePlayers[game.id[j]]) {
                continue;
            }

            if (!mem.gamePlayers[game.id[j]].robot) {
                save.escapee(game.id[j], mem.gamePlayers[game.id[j]].cid, mem.gamePlayers[game.id[j]].uuid, escapeCoin, coinType);
            } else {
                save.robotEscapee(game.id[j], escapeCoin, coinType);
            }
            delete mem.gamePlayers[game.id[j]];
        }
        if (game.ddz) {
            //game.ddz.close();
            //game.ddz = null;
            mem.games[game.gameId].ddz.close();
            mem.games[game.gameId].ddz = null;
        }
        mem.games[game.gameId] = null;
        delete mem.games[game.gameId];
        let param = {};
        param.gameId = gameId;
        rpc.dc.send('delGame', param);
        if (gameData.d.gameLv[gameLv].type == 'custom') {
            rpc.dc.send('delRecruit', param);
        }
        log.p('all exit kill room', gameId);
    }
};
method.praise = function (obj, cid, data) {
    save.taskUpdate(obj.userId, null, null, 4, 1);
    let param = {};
    param.userId = obj.userId;
    param.target = data.target;
    rpc.dc.send('setGamePraise', param);
};
method.rpcInMatch = function (obj, cid, data) {

    rpc.match.send('rpcInGame')
};


function getGame(obj, cid) {
    if (obj.gameId && !mem.games[obj.gameId]) {
        msg.send(cid, obj.uuid, 'error', {'code': 10032});
        save.clearGameId(obj.userId, cid, obj.uuid);
        return false;
    }
    if (!mem.gamePlayers[obj.userId]) {
        msg.send(cid, obj.uuid, 'error', {'code': 10036});
        save.clearGameId(obj.userId, cid, obj.uuid);
        return false;
    }
    if (!mem.gamePlayers[obj.userId].gameId) {
        msg.send(cid, obj.uuid, 'error', {'code': 10037});
        save.clearGameId(obj.userId, cid, obj.uuid);
        return false;
    }
    let game = mem.games[mem.gamePlayers[obj.userId].gameId];
    if (!game) {
        msg.send(cid, obj.uuid, 'error', {'code': 10031});
        return false;
    }
    return game;
}

function broadcast(ids, action, obj) {
    for (let i in ids) {
        if (!mem.gamePlayers[ids[i]]) {
            continue;
        }
        if (!mem.gamePlayers[ids[i]].cid || !mem.gamePlayers[ids[i]].uuid) {
            continue;
        }
        if (mem.gamePlayers[ids[i]].line == 'off') {
            continue;
        }
        msg.send(mem.gamePlayers[ids[i]].cid, mem.gamePlayers[ids[i]].uuid, action, obj);
    }
}